package mathy.wili.c;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import mathy.c.Ca;
/**
 * 
 * @author weila 2021年1月4日
 */
public class Src9 {
	static final String NL = Str9.NL;
	/**
	 * 
	 * @param findContent  true:仅当后面仅替换注释内容，但保留边界
	 * @param s0
	 * @param replaceRangeList
	 * @return
	 */
	static List<int[]> find_javaComment_and_quoteContent_asRangeList(boolean findContent, String s0,
			List<int[]> replaceRangeList) {
		int length = s0.length();
		Pattern pat = Pattern.compile("\"|\'|//|/\\*");
		Matcher mat = pat.matcher(s0);
		int from;
		while (mat.find()) {
			if (++inc2 == 7219)
				Ca.pause();
			if (replaceRangeList == null)
				replaceRangeList = new ArrayList<>(30);
			String find = mat.group(), st;
			if (find.equals("\"") || find.equals("'")) {
				st = Str9.readQuote(s0, mat.start());
				//System.out.println(st);
				from = mat.start() + st.length();
				if (findContent) {
					replaceRangeList.add(new int[] { mat.start(), from });
				} else {
					if (st.length() != 3) {
						replaceRangeList.add(new int[] { mat.start() + 1, from - 1 });//引号中的内容
					} else {//eg. "("
						replaceRangeList.add(new int[] { mat.start() + 1, from - 1 });//引号中的内容
					}
				}
				mat.region(from, length);
			} else if (find.equals("//")) {
				int ind = s0.indexOf(NL, mat.end());
				if (ind == -1) {
					if (findContent)
						replaceRangeList.add(new int[] { mat.start(), length });
					else
						replaceRangeList.add(new int[] { mat.start() + 2, length });
					return replaceRangeList;//maybe
				}
				if (findContent)
					replaceRangeList.add(new int[] { mat.start() + 2, ind });//不包括终止下标
				else
					replaceRangeList.add(new int[] { mat.start(), ind });//不包括终止下标
				mat.region(ind + 1, length);
			} else if (find.equals("/*")) {
				int ind = s0.indexOf("*/", mat.end());
				if (findContent)
					replaceRangeList.add(new int[] { mat.start() + 2, ind });//整个注释
				else
					replaceRangeList.add(new int[] { mat.start(), ind + 2 });//整个注释
				mat.region(ind + 2, length);
			}
		}
		return replaceRangeList;
	}
	public static final String field = "F";
	/**
	 * 	note: 行号统计当在替换注释之前进行，因注释中可换行。
	 */
	public static String replace_javaComment_and_quotes_withSameLengthSpace(String s0, List<int[]> replaceRangeList) {
		find_javaComment_and_quoteContent_asRangeList(false, s0, replaceRangeList);
		s0 = Str9.replaceAllRangeList_withChars(replaceRangeList, ' ', s0);
		return s0;
	}
	static final String MethodHeadPat1 = "|\n[ \f\t\\w<\\?>,\\[\\]]+?(\\w+)\\(";

	static final String MethodHeadPat = "|\n[\\w\\s<\\?>,&\\[\\]]+?([\\w\\$]+)\\(";
	/**
	 * 	难以split by ',' , 因不知大小于号是泛型边界还是算符。eg. static Map<Method, String> map = new HashMap<>(), b=c;
	 * @param fieldLine  eg. int aa = 11, bb = 22, cc = 33;
	 */
	public static List<Object[]> readFieldRange_asList(String s0, int fromInd, int toInd) {
		//难处：不知小于号是泛型边界还是算符。eg. static Map<Method, String> map = new HashMap<>(), b=a<b ?c:d;
		String fields = s0.substring(fromInd, toInd);
		Pattern pat = Pattern.compile("[,\\(\\{\\[;]|[^=]=[^=]|[^\\s]<");//基于假定：泛型左括前必无空格
		Matcher mat = pat.matcher(fields);
		List<Object[]> lis = new ArrayList<>();
		int eqIndex = -1, fieldFrom = 0, inc = 0;
		String field;
		while (mat.find()) {
			if (++inc == 99)
				fields.substring(mat.start());
			String matchSt = mat.group();
			char ch;
			if (matchSt.length() == 3) {
				ch = matchSt.charAt(1);
			} else {
				ch = matchSt.charAt(matchSt.length() - 1);
			}
			if (ch == ',' || ch == '=' || ch == ';') {
				if (eqIndex != -1) {
					if (ch == '=')
						continue;//赋值号右侧也可能含有等号； eg. boolean is = a>=3;
					Ca.asert(ch != '=', ch);
					lis.get(lis.size() - 1)[2] = fromInd + mat.start();//上一属性终止于逗等号前
					fieldFrom = mat.end();//上属性初始化结束，下一属性开始
					eqIndex = -1;
					continue;
				}
				field = fields.substring(fieldFrom, mat.start());
				field = Str9.trimR(field);
				int nameStartInd = field.lastIndexOf(' ');
				String name = nameStartInd == -1 ? field.trim() : field.substring(nameStartInd).trim();
				//nameStartInd = fromInd + fieldFrom;
				nameStartInd = fromInd + fieldFrom + nameStartInd;
				if (ch == ',' || ch == ';') {
					//lis.add(new Object[] { name, fromInd + fieldFrom, fromInd + mat.start() });
					lis.add(new Object[] { name, nameStartInd, fromInd + mat.start() });
					fieldFrom = mat.end();//本属性未初始化，下一属性开始
					eqIndex = -1;
				} else {
					//lis.add(new Object[] { name, fromInd + fieldFrom, -1 });
					lis.add(new Object[] { name, nameStartInd, -1 });
					eqIndex = mat.start();//本属性进入初始化。
				}
				continue;
			} else {
				String qt = null;
				if (ch == '(' || ch == '{' || ch == '[' || ch == '(') {
					qt = Str9.readBracket(fields, mat.start(), true);
				} else if (ch == '<') {
					qt = Str9.readBracket(fields, mat.start() + 1, false);
				}
				mat.region(mat.start() + qt.length(), fields.length());
				continue;
			}
		}
		Ca.asert(fields.charAt(fields.length() - 1) == ';', fields);
		lis.get(lis.size() - 1)[2] = fromInd + fields.length();//最后一个属性终止于分号后
		return lis;
	}
	static final int aa = 1;

	final static int bb = 2;

	final public static int cc = 3;
	/**
	 * 	若类非文件首类，据此可找到其在哪个文件中。<br>
	 * 	...一个文件有一个首类和n个兄弟类（首类类名即文件名）.
	 * @return { root,file }
	 */
	public static File[] findJavaFile_ofClass(Class<?> cls, File[] srcRoots, Map<Class<?>, Object[]> toMap) {
		if (cls.getName().indexOf('$') != -1)
			return null;
		String path = cls.getPackageName().replace('.', '/');
		Pattern pat = Pattern.compile("\\s*(class|interface|enum)\\s+(\\w+)\\s+");
		for (File root : srcRoots) {
			File dir = new File(root, path);
			if (!dir.exists())
				continue;
			File[] ff = dir.listFiles((File file) -> file.getName().endsWith(".java"));
			for (File file : ff) {
				String s0 = File9.strOfFile(file);
				Matcher mat = pat.matcher(s0);
				boolean find = false;
				while (mat.find()) {
					String cname = mat.group(2);
					int indL = s0.indexOf('{', mat.end());
					String st = Str9.readJavaBracket('{', '}', s0, indL);
					int indR = indL + st.length();
					Class<?> curCls = Class9.forName(cls.getPackageName() + "." + cname, -1);
					toMap.put(curCls, new Object[] { root, file, mat.start(), indL, indR });
					mat.region(indR, s0.length());
					if (cls.getSimpleName().contentEquals(cname))
						find = true;
				}
				if (find)
					return new File[] { root, file };
			}
		}
		return null;
	}
	static int inc, inc2;
}
